SQLite数据库文件格式逐字节详解

您所在的位置:网站首页 wpf format SQLite数据库文件格式逐字节详解

SQLite数据库文件格式逐字节详解

#SQLite数据库文件格式逐字节详解| 来源: 网络整理| 查看: 265

sqlite用B+树的形式组织数据库中的数据。B+树有内部节点和叶子节点两种节点,对应的,数据库文件也有内部节点页和叶子节点页。 数据库中存储着两种数据,一种是表中的数据的集合(这些数据构成了一个表),一种是所有表的根节点集合(所有的表的根节点构成了master_catalog)。这两种数据都是通过B+树组织起来的,数据库文件中4KB大小的一个部分构成B+树的一页。

执行命令:”create table t1(a char, b char)” 和 “insert into t1 values(‘t’,’t’)” ,可以得到如下的数据库文件。文件大小是8KB,即2页,每页4KB。第一页是master_catalog,是叶子节点页,存储了所有的表的根节点,第二页也是叶子节点页,存储了表中具体的数据。我截取了有数据的部分,接下来我将逐个字节介绍sqlite的数据库文件格式。

Alt text Alt text Alt text Alt text

数据库文件的第一页很特殊,它会包含一个100bytes大小的文件头。在本例中0x00~0x63是文件头。下面介绍文件头的格式:

0x00~0x0f: 字符串“SQLite format 3” 0x10~0x11: 页大小 0x12: 文件写格式 (1 for legacy; 2 for WAL) 0x13: 文件读格式 0x14: 每页底部保留bytes数(默认是0) 0x15: 内部节点页的最大嵌入负载(嵌入负载是个百分数,0~255代表0%到100%),这个值是用来限制最大的单个record的,如果最大嵌入负载是25%,那么单条record就不能超过1/4页,超过的部分会转移到溢出页 0x16: 内部节点页的最小嵌入负载 0x17: 叶子节点页的最小嵌入负载,叶子节点页的最大负载永远是100%,所以只给出叶子节点页的最小负载限制 0x18~0x1b: 文件被修改的次数,本例中该值是2,创建table和插入数据共修改了两次文件 0x1c~0x1f: 保留字节 0x20~0x23: 自由页链表头 0x24~0x27: 自由页页数 0x28~0x63: 15个4bytes的元数据

0x28~0x2b: schema cookies 0x2c~0x2f: schema格式 0x30~0x33: 默认页缓存大小 0x34~0x37: 在自动清空模式或者增量清空模式下,这个值是数据库文件中最大的B树根节点页。在其他模式下,这个值是0. 0x38~0x3b: 文本编码格式。A value of 1 means UTF-8. A value of 2 means UTF-16le. A value of 3 means UTF-16be. 0x3c~0x3f: 用户版本号。 0x40~0x43: 非零表示增量清空模式。零表示其他模式。 0x44~0x47: 应用程序号,用于表明sqlite属于特定的应用程序。 0x44~0x5b: 保留字节。 0x5c~0x5f: 最近修改数据库文件的sqlite库版本。 0x60~0x63: 保留字节。

接下来是正常的b+树节点页的页头。在本例中,第1页(master catalog)存储了所有的表,由于master catalog也是通过b+树组织的,而本例中只有一个表,第1页没有占满,所以第1页是master catalog所代表的b+树的叶子节点,也是master catalog所代表的b+树的唯一节点。

0x64: b树节点页类型。0x0d表示表的b+树的叶子节点页。 0x65~0x66: 第一个自由块的位置,自由块通过链表链接起来。自由块通常是由于cell的删除或更新产生的,自由块缩小到一定程度就成为了碎片,sqlite会按照一定的逻辑判断碎片数量并进行碎片整理。 0x67~0x68: 本页中cell的数量。本例中是1,这个cell存储了表t1。 0x69~0x6a: 第一个cell的偏移量。本例中是0xfd0 + 0。 0x6b: 碎片空间总大小。接下来的4bytes应该是最右孩子节点。但是这是叶子节点页,没有孩子,所以这4bytes省略了。 0x6c~0x6d: 指出cell的偏移量。具体参考官方文档中cell和cell pointer的存储方式。

接下来就是cell的格式了,存储位置为0xfd0~0xfff。cell的开头4bytes是左孩子的页号,但是本例中这一页是叶子节点页,没有孩子节点,所以这4bytes省略了。

0xfd0: 用变长度方式存储的数据大小,本例中是46,即从0xfd2到0xfff共46bytes数据。关于变长度方式存储,参见我的另一篇文章 SQLite 变长度整型(varint)编码解码方法 。 0xfd1: 键值大小,如果键值是整型变量,那么这个值就是键值本身。本例中sqlite为表t1自动分配了一个键值01。 0xfd2: header size。本例中是06,即0xfd3到0xfd7都是数据类型。数据类型的具体定义见官方文档。 0xfd3: 17转化为十进制就是23,(23-13)/2 = 5,代表第一个数据是5个字节大小的text,即“table”。 0xfd4: 11转化为十进制就是17,(17-13)/2 = 2,即t1。 0xfd5: 同上。 0xfd6: 以二进制补码形式存储的整型数据所占的byte。对应0xfe1的02,02是1byte。 0xfd7: 49转化为十进制就是73,(73-13)/2 = 30,即0xfe2到0xfff,刚好30个bytes。

至此,第一页已经介绍完了。接下来进入第二页,相较于第一页存储表本身的信息,第二页存储了表t1中的数据。

0x1000: b树节点页类型。0x0d表示表的b+树的叶子节点页。 0x1001~0x1002: 第一个自由块的位置。 0x1003~0x1004: 本页中cell的数量。本例中是1,这个cell存储了数据“tt”。 0x1005~0x1006: 第一个cell的偏移量。本例中是0xff9+1000。 0x1007: 碎片空间总大小。接下来的4bytes应该是最右孩子节点。但是这是叶子节点页,没有孩子,所以这4bytes省略了。 0x1008~0x1009: 指出cell的位置,即下面0x1ff9处的cell。 0x1ff9: 表示cell header有5个元素,即05 01 03 0f 0f。 0x1ff9~0x1ffd: 01是键值大小,如果键值是整型变量,那么这个值就是键值本身。本例中sqlite为数据“tt”自动分配了一个键值01。 0x1ffb: 03是header size,即接下来的0f 0f都表示数据类型。 0x1ffc~0x1ffd: 0f转化为十进制就是15,(15-13)/2 = 1,表示一个字节的text类型。 0x1ffe~0x1fff: 以ascii码形式保存的数据本身,即’t’。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3